package no.ntnu.idi.deid.patternmatching.search.dictionary.lucene;

import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import no.ntnu.idi.deid.searchresultunits.CategoryTag;

import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.FSDirectory;

public class SearchField {
	
	private static final int NUMBER_OF_HITS = 20;
	
	private IndexReader reader;
	private IndexSearcher searcher;
	private TopScoreDocCollector collector;
	private ScoreDoc[] latestSearchResult; //Det er her resultatet blir lagra til slutt
	
	//Konstruktør
	private SearchField(IndexReader reader, TopScoreDocCollector collector)
	{
		init(reader);
		this.collector = collector;
	}
	
	//Konstruktør 2
	private SearchField(IndexReader reader)
	{
		init(reader);
	}
		
	//kaller konstruktør 1
	protected static SearchField createSearchFieldFrom(IndexReader reader, TopScoreDocCollector collector)
	{
		return new SearchField(reader, collector);
	}
	
	//kaller konstruktør 2
	protected static SearchField createSearchFieldFrom(IndexReader reader, IndexSearcher searcher)
	{
		return new SearchField(reader);
	}
	
	//Kaller generateStandardSearchField(File) men tar inn en string i stedet for File
	public static SearchField generateStandardSearchField(String IndexLocation) throws IOException
	{
		File file = new File(IndexLocation);	
		return SearchField.generateStandardSearchField(file);
	}
	
	//Denne returnerer en searchfield-instans. Den kaller konstruktøren med de instillingene som er "Standard". 
	//Bør nesten alltid brukes, Etter at denne er kjørt, kan man søke inn i indeksen ved hjelp av søkemetoden.
	protected static SearchField generateStandardSearchField(File IndexLocation) throws IOException
	{
		
		return SearchField.createSearchFieldFrom(DirectoryReader.open(FSDirectory.open(IndexLocation)),TopScoreDocCollector.create(NUMBER_OF_HITS, true));
	}
	
	//en metode som lager searcheren basert på reader. Brukes seinere, fordi det er searcher man søker i.
	private void init(IndexReader reader)
	{
		this.reader = reader;
		this.searcher = new IndexSearcher(reader);
	}
	
	//Denne lager collectoren, for å forstå helt hva det betyr må man inn i Lucene dokumentasjonen, men det er i collectoren at resultatet
	//av et søk legges. Jeg har laget det slik at den bare returnerer 20 av treffa, siden vi bare trenger å vite om det var en treff på søket eller
	// ikke. 
	protected void generateStandardTopDocsCollector()
	{
		collector = TopScoreDocCollector.create(NUMBER_OF_HITS, true);
	}
		
	//closer readeren, må alltid gjøres når man er ferdig å søke.
	public void closeReader() throws IOException
	{
		reader.close();
	}
	
	
	public Set<CategoryTag> searchAndReturnSet(Query query) throws IOException
	{
		search(query);
		Set<CategoryTag> returnList = new HashSet<CategoryTag>();
		for(int i = 0; i < latestSearchResult.length; i++ ){
			String type = searcher.doc(latestSearchResult[i].doc).get(IndexBuilder.FIELD_TYPE);
			CategoryTag categoryTag = CategoryTag.getCategoryTagByString(type);
			returnList.add(categoryTag);
		}
		return returnList;		
	}
	
	public void search(Query query) throws IOException {
		searcher.search(query, collector); //søker og legger resultatet i collector
		latestSearchResult = collector.topDocs().scoreDocs;//henter ut resultatet og legger det i latestSearchResult. 
	}	
}
